package thread;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * ABA问题
 */
public class ABADemo {

    //带有时间戳的原子引用 (共享内存值100， 版本号为1)
    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);
    public static void main(String[] args) {
        System.out.println("=========ABA问题的解决===========");
        new Thread(() -> {
            //获取第一次的版本号
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + "\t第一次版本号" + stamp);
            //CAS 共享内存值100和期望值100比较相等,且共享内存时间戳和预期值时间戳相等;返回值为true且将共享内存值修改为111时间戳为2;
            try {//休眠一秒,模拟并发，给ThreadA预留时间启动。
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicStampedReference.compareAndSet(
                    100,
                    111,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1

            );
            System.out.println(Thread.currentThread().getName() + "\t第二次版本号：" + atomicStampedReference.getStamp());
            //CAS 共享内存值111和期望值111比较相等,且共享内存时间戳和预期值时间戳相等;返回值为true且将共享内存值修改为100时间戳为3;
            atomicStampedReference.compareAndSet(
                    111,
                    100,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1
            );
            System.out.println(Thread.currentThread().getName() + "\t第三次版本号：" + atomicStampedReference.getStamp());

        }, "ThreadB").start();


        new Thread(() -> {
            //获取第一次的版本号
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + "\t第一次版本号" + stamp);
            //CAS 休眠3秒，与ThreadB时间差。模拟挂起;让ThreadB先执行,经过线程B的操作当前共享内存值为100，时间戳为3
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //共享内存值100和期望值100比较相等,但是共享内存时间戳3和预期值时间戳1不相等;返回值为false,不修改共享内存值和时间戳;
            boolean result = atomicStampedReference.compareAndSet(
                    100,
                    2020,
                    stamp,
                    stamp + 1
            );
            System.out.println(
                    Thread.currentThread().getName()
                            + "\t修改是否成功：" + result
                            + "\t当前最新的版本号：" + atomicStampedReference.getStamp()
                            + "\t当前最新的值：" + atomicStampedReference.getReference()
            );
        }, "ThreadA").start();
        //=========ABA问题的解决===========
        //ThreadB	第一次版本号1
        //ThreadA	第一次版本号1
        //ThreadB	第二次版本号：2
        //ThreadB	第三次版本号：3
        //ThreadA	修改是否成功：false	当前最新的版本号：3	当前最新的值：100
    }
}
